const util = {
  // 常量
  FALSE_MSG: '操作失败！',
  SUCCESS_MSG: '操作成功！',
  AJAX_MSG: '系统出现异常，请联系管理员进行解决。',
  VALIDATE_ERROR: '表单域验证错误，请检查所有填写的表单域！',
  // 正则
  REGEXP: {
    // 链接
    url: /^((http|https):\/\/(\w+:{0,1}\w*@)?(\S+)|)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?$/,
    // 手机
    mobile: /^1[345678]\d{9}$/,
    // 座机
    tel: /^(0[0-9]{2,3})-?([0-9]{7,8})$/,
    // 邮编
    post: /^\d{6}$/,
    // 邮箱
    email: /^[A-Z_a-z0-9-.]+@([A-Z_a-z0-9-]+\.)+[a-z0-9A-Z]{2,4}$/,
    // 图片
    pic: /[^\s]+\.(jpg|jpeg|gif|png|bmp|svg|webp)/i,
    // 数字
    number: /^[0-9]+$/
  }
}

/**
 * 翻页（全部数据版）
 * @param lists 数据列表
 * @param baseSize 每页个数
 * @param total 总个数
 * @constructor
 */
class Paging {
  constructor (lists, baseSize, total) {
    this.lists = lists || []
    this.baseSize = baseSize || 15
    this.selectSize = baseSize || 15 // 所选个数
    this.total = total || this.lists.length
    this.pageTotal = Math.ceil(this.total / this.selectSize) // 总页数
    this.pageSizes = [] // 每页个数列表
    this.currentPage = 1
    this.pageSize = this.baseSize
    this.pageSizes = this.pageSizeHandle()
    this.currentPage = 1
  }
  pageSizeHandle () {
    let arr = []
    let i = 1
    let sizeItem = this.baseSize

    while (sizeItem < this.total) {
      sizeItem = Math.pow(this.baseSize, Math.ceil(i / 5)) * (i % 5 || 5)
      i++
      arr.push(sizeItem)
    }

    arr = arr.length <= 0 ? [sizeItem] : arr
    return arr
  }
  /**
   * 更新列表
   * @param lists
   */
  updateList (lists) {
    this.lists = lists || []
    this.update(this.lists.length)
  }
  /**
   * 更新列表总个数
   * @param total
   */
  update (total) {
    this.total = total
    this.pageTotal = Math.ceil(this.total / this.selectSize) // 总页数
    this.pageSizes = this.pageSizeHandle() // 每页个数列表
  }
  /**
   * 获取当前页列表
   * @param currentPage
   * @returns {Array.<T>}
   */
  getLists (currentPage) {
    this.currentPage = currentPage && currentPage <= this.pageTotal ? currentPage : 1
    return this.lists.slice((this.currentPage - 1) * this.selectSize, this.currentPage * this.selectSize)
  }
  /**
   * 每页显示个数改变
   * @param size
   */
  sizesChange (size) {
    this.selectSize = size
    this.pageTotal = Math.ceil(this.total / this.selectSize)
  }
  updataCurrentPage (val) {
    this.currentPage = val
  }
}
util.Paging = Paging

/**
 * form表单提交
 * @param url 请求url
 * @param data 请求数据
 */
util.formSubmit = (url, data) => {
  var timestamp = new Date().getTime()
  var form = document.createElement('form')
  form.setAttribute('id', 'J_form_' + timestamp)
  form.setAttribute('action', url)
  form.setAttribute('method', 'POST')
  form.setAttribute('encoding', 'multipart/form-data')
  form.setAttribute('style', 'display:none')

  for (var key in data) {
    var input = document.createElement('input')
    input.setAttribute('name', key)
    if (data[key] !== null && typeof data[key] !== 'undefined') {
      input.setAttribute('value', data[key])
    }
    form.appendChild(input)
  }
  document.querySelector('body').appendChild(form)
  form.submit()
}

/**
 * 验证函数
 */
util.validatorFn = {
  /**
   * 人民币小数位数限制检查
   * @param maxDigits 最大小数位 元最大2位，万元最大6位
   * @returns {Function}
   */
  rmbDecimalDigits: function (maxDigits) {
    const _maxDigits = maxDigits || 2

    return function (rule, value, callback) {
      var _val = value.toString()

      if (_val.indexOf('.') !== -1 && _val.slice(_val.indexOf('.') + 1).length > _maxDigits) {
        callback(new Error('最大小数位数为' + _maxDigits))
      } else {
        callback()
      }
    }
  },
  urlValidator: function (rule, value, callback) {
    if (!util.REGEXP.url.test(value)) {
      callback(new Error('不是一个有效的url！'))
    } else {
      callback()
    }
  },
  /**
   * 手机号验证
   * @param rule
   * @param value
   * @param callback
   */
  mobilePhone: function (rule, value, callback) {
    if (!util.REGEXP.mobile.test(value)) {
      callback(new Error('手机号码不正确！'))
    } else {
      callback()
    }
  },
  /**
   * 座机号验证
   * @param rule
   * @param value
   * @param callback
   */
  telPhone: function (rule, value, callback) {
    if (!util.REGEXP.tel.test(value)) {
      callback(new Error('座机号码不正确！'))
    } else {
      callback()
    }
  },
  /**
   * 手机加座机验证
   * @param rule
   * @param value
   * @param callback
   */
  telAndMobile: function (rule, value, callback) {
    if (!util.REGEXP.tel.test(value) || !util.REGEXP.mobile.test(value)) {
      callback(new Error('电话号码不正确！'))
    } else {
      callback()
    }
  },
  /**
   * 邮编验证
   * @param rule
   * @param value
   * @param callback
   */
  postCode: function (rule, value, callback) {
    if (!util.REGEXP.post.test(value)) {
      callback(new Error('座机号码不正确！'))
    } else {
      callback()
    }
  },
  /**
   * 邮箱验证
   * @param rule
   * @param value
   * @param callback
   */
  email (rule, value, callback) {
    if (!util.REGEXP.email.test(value)) {
      callback(new Error('邮箱格式不正确！'))
    } else {
      callback()
    }
  }
}

/**
 * paddStringToUrl 将对象转化为问号参数形式添加在url地址的后面，会进行URI编码处理
 * @param url 原url地址
 * @param param 参数对象
 * @returns '' 返回拼接好的新url地址
 */
util.addStringToUrl = function (url, param) {
  if (!param) {
    return url
  }

  var hasSearch = /\?/.test(url)
  var data = this.encodeToURIString(param)

  return url + (hasSearch ? '&' : '?') + data
}

/**
 * encodeToURIString 把一个对象类型转化为问号参数类型的字符串
 * @param data 要解析的对象
 * @param isUIR 是否转化为URIComponent，默认转化，只有当值为false时，不转化
 * @returns '' 问号参数类型的字符串
 */
util.encodeToURIString = function (data, isUIR) {
  if (!data) {
    return ''
  }
  if (typeof data === 'string') {
    return data
  }
  var ary = []
  if (Object.prototype.toString.call(data) === '[object Object]') {
    for (var key in data) {
      if (data.hasOwnProperty(key)) {
        if (isUIR) {
          try {
            key = decodeURIComponent(key)
            data[key] = decodeURIComponent(data[key])
            ary.push(key + '=' + encodeURIComponent(data[key]))
          } catch (ex) {
            ary.push(key + '=' + data[key])
          }
        } else {
          ary.push(key + '=' + data[key])
        }
      }
    }
  }
  return ary.join('&')
}
// 序列化表单数据
util.getJson = function (params) {
  var param = ''
  for (let item in params) {
    param += (item + '=' + params[item] + '&')
  }
  return param.substring(0, param.length - 1)
}

/**
 * getParam 解析url问号参数
 * @param url 要解析的字符串
 * @returns {{}} 解析完成的对象
 */
util.getParam = function (url = location.href) {
  var obj = {}
  url.replace(/([^?=&#]+)=([^?=&#]+)/g, function () {
    // 去除首尾空格
    obj[arguments[1]] = arguments[2]
  })
  return obj
}

/**
 * 打开新的窗口
 * @param {object} params - 参数对象
 * @param {string} [params.width = 800] - 窗口的宽度
 * @param {string} [params.height = 400] - 窗口的高度
 * @param {string} [params.type] - 定义新窗口打开的方式，如果取值不为空，则在新的 tab 中打开，否则在当前页面弹出
 * @param {string} params.url - 新窗口打开的 url
 */
util.openWindow = function ({width = 800, height = 400, type = '', url = ''} = {}) {
  if (!url) {
    alert('缺少必要参数: url')
    return
  }
  if (!type) {
    const baseline = 30
    const top = (window.screen.availHeight - height - baseline) / 2
    const left = (window.screen.availWidth - width - baseline) / 2
    window.open(url, '', `width=${width},height=${height},top=${top},left=${left},status=yes,toolbar=no,menubar=no,location=no,scrollbars=yes,resizable=yes`)
  } else {
    window.open(url)
  }
}

/**
 * 关闭页面
 * @param {string} [callback] - 关闭的同时执行的回调，可选
 * @param {boolean} [reload] - 关闭的同时刷新来源页，可选
 */
util.closeWindow = function (callback, reload) {
  if (typeof callback === 'function') callback()
  if (window.opener) {
    window.close()
    reload && window.opener.location.reload()
  }
}

/**
 * 设置页面中 table 的高度
 * @param {number} value - 其他需要减去的值
 */
util.setTableHeight = function (value = 0) {
  const containerPadding = 40
  const titleOuterHeight = 70
  const pageOuterHeight = 50
  const tablePadding = 42
  const clientHeight = document.documentElement.clientHeight

  return clientHeight - containerPadding - titleOuterHeight - pageOuterHeight - tablePadding - value
}

/**
 * 获取数组对象中的值
 * @param {array} source - 数组源 [{value: 0, label: '已取消'}]
 * @param {number|string} value - 数组中对象的值
 */
util.getArrayValue = function (source, value) {
  if (!value) return
  let label = ''
  source.forEach((item) => {
    if (item.value === value) label = item.label
  })

  return label
}
/**
 * getUrl 通过url判断当前环境
 * @param url 要解析的字符串
 * @returns '' 解析返回当前环境字符串
 */
util.getUrl = function (url = location.href) {
  const Reg = /:\/\/([^:./?]+)?\./
  const sTmp = Reg.exec(url)
  console.log(sTmp)
  const env = !sTmp ? 'test' : (sTmp[1].indexOf('test') ? 'test' : (sTmp[1].indexOf('pre') ? 'pre' : ''))
  return env
}

// 格式化日期（2018-10-27）
util.formatDate = function (str) {
  return parseTime(str, '{y}-{m}-{d}')
}

// 格式化时间（2018-10-27 12:34:57）
util.formatDateTime = function (str) {
  return parseTime(str)
}

// 解析时间
export function parseTime (time, cFormat) {
  if (arguments.length === 0) {
    return null
  }
  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    if (('' + time).length === 10) time = parseInt(time) * 1000
    date = new Date(time)
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }
  const timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
    let value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') {
      return ['日', '一', '二', '三', '四', '五', '六'][ value ]
    }
    if (result.length > 0 && value < 10) {
      value = '0' + value
    }
    return value || 0
  })
  return timeStr
}

export default util
